package top.malaoshi.webmvc.parameter;

import top.malaoshi.webmvc.info.MethodsArgumentInfo;
import top.malaoshi.webmvc.exception.ParameterTypeMatchValueException;
import top.malaoshi.webmvc.exception.RequestParamResolverException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;

/**
 * 数组类型是基本数据类型的包装类型，包括：
 * Short、Integer、Long、Float、Double、Boolean
 */
public class BaseTypeWrappeArrayrResolver extends AbstractResolver implements RequestParamAndMethodArgsResolver {
    @Override
    public Object resolver(HttpServletRequest request, HttpServletResponse response , MethodsArgumentInfo mai) throws RequestParamResolverException {

        checkNameAndValue(mai);
        String parameterName = getName(mai);
        String[] valueStrs = request.getParameterValues(parameterName);
        // 获取数组元素的类型
        Class elementType = mai.getElementType();
        Object ret = null;
        // 如果Controlle中形参是 基本类型的包装类型，而且没有required为true，那么可以为null
        if(valueStrs!=null ) {
            int len = valueStrs.length;
            // 创建数组
            ret = Array.newInstance(elementType, len);
            // 遍历数组
            for(int i=0;i<len;i++) {
                // 根据数组元素的类型，创建包装类对象
                Constructor constructor = null;
                try {
                    constructor = elementType.getConstructor(String.class);
                } catch (NoSuchMethodException e) {
                    throw new RequestParamResolverException(e);
                }
                try {
                    Object value = constructor.newInstance(valueStrs[i]);
                    Array.set(ret,i,value);
                } catch (Exception e) {
                    // 如果valueStr为非数字字符串
                    String msg = String.format("从request取出的值是[ %s ]，但形参[ %s ]类型是[ %s ]，不能赋值",
                            valueStrs[i], mai.getName(), mai.getElementType().getName());
                    throw new ParameterTypeMatchValueException(msg);
                }
            }
        }
        checkRequired(ret,mai);
        return ret;
    }
}
